package com.ktwlsoft.archivemanage.service.utils;

import com.ktwlsoft.archivemanage.config.FileStorageProperties;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.stereotype.Component;
import ws.schild.jave.*;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;

/**
 * 视频缩略图截取工具类(包含视频转格式)
 *
 * @author Name on 2020/9/14 17:59
 * @version 1.0
 */
@Component
public class SmartFileUtils {

    /**文件路径*/
    private static FileStorageProperties fileStorageProperties;

    /**文件路径*/
    private final FileStorageProperties i_fileStorageProperties;

    public SmartFileUtils(FileStorageProperties i_fileStorageProperties) {
        this.i_fileStorageProperties = i_fileStorageProperties;
    }

    @PostConstruct
    public void init(){
        fileStorageProperties = this.i_fileStorageProperties;
    }

    /**
     * * 截取视频第六帧的图片
     *
     * @param filePath      视频路径
     * @return String       图片的路径
     * @throws FrameGrabber.Exception FrameGrabber.Exception
     */
    public static String videoImage(String filePath) throws FrameGrabber.Exception {
        return videoImage(filePath,null,null);
    }

    /**
     * * 截取视频第六帧的图片
     *
     * @param filePath      视频路径
     * @param dir           文件存放的目录 默认uploads/thumbnail
     * @return String       图片的路径
     * @throws FrameGrabber.Exception FrameGrabber.Exception
     */
    public static String videoImage(String filePath, String dir) throws FrameGrabber.Exception {
        return videoImage(filePath,dir,null);
    }

    /**
     * * 截取视频第六帧的图片
     *
     * @param filePath      视频路径
     * @param dir           文件存放的目录 默认uploads/thumbnail
     * @param videoType     视频格式 默认MP4
     * @return String       图片的路径
     * @throws FrameGrabber.Exception FrameGrabber.Exception
     */
    public static String videoImage(String filePath, String dir,String videoType) throws FrameGrabber.Exception {
        String pngPath = "";
        String retPath = "";
        //转视频格式
        String avToMp4NewPath = avToMp4(filePath,filePath.substring(0,filePath.lastIndexOf(".")) + "(avToMp4)." + "mp4");
        //获取视频
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(avToMp4NewPath);
        if(videoType != null && !"".equals(videoType.trim())){
            ff.setFormat(videoType);
        }else {
            ff.setFormat("mp4");
        }
        ff.start();
        //得到视频帧数
        int ffLength = ff.getLengthInFrames();
        Frame f;
        int i = 0;
        while (i < ffLength) {
            f = ff.grabImage();
            //截取第6帧
            if (i > 5 && f.image != null) {
                //执行截图并放入指定位置
                if(dir != null && !"".equals(dir.trim())) {
                    pngPath = dir + File.separator + getPngName();
                    retPath = pngPath;
                }else{
                    String fileName = getPngName();
                    pngPath = Paths.get(fileStorageProperties.getUploadDir()).toAbsolutePath().normalize() + File.separator + "thumbnail" + File.separator + fileName;
                    retPath = "thumbnail" + File.separator + fileName;
                }
                doExecuteFrame(f, pngPath);
                break;
            }
            i++;
        }
        ff.stop();
        //删除新生成的视频文件
        FileUtils.deleteFile(avToMp4NewPath);
        return retPath;
    }

    /**
     * 生成图片的名称
     *
     * @return 图片的名称 例：10137a1681ee4f6cb8fd027832e08710.png
     */
    private static String getPngName() {
        return UUID.randomUUID().toString().replace("-", "") + ".png";
    }

    /**
     * 截取缩略图
     *
     * @param f                 Frame
     * @param targerFilePath    封面图片存放路径
     */
    private static void doExecuteFrame(Frame f, String targerFilePath) {
        String imagemat = "png";
        if (null == f || null == f.image) {
            return;
        }
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bi = converter.getBufferedImage(f);
        File output = new File(targerFilePath);
        try {
            Files.createDirectories(Paths.get(output.getPath()));
            ImageIO.write(bi, imagemat, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
      * 视频转MP4 on 2020/9/28 11:16
      *
      * @param oldPath 旧视频地址
      * @param newPath 新视频地址
      * @return String 新视频地址
      */
    public static String avToMp4(String oldPath,String newPath) {
        //音频编码格式
        AudioAttributes audio = new AudioAttributes();
        audio.setCodec("libmp3lame");
        audio.setBitRate(800000);
        audio.setChannels(1);
        //视频编码格式
        VideoAttributes video = new VideoAttributes();
        video.setCodec("libx264");
        video.setBitRate(3200000);
        //数字设置小了，视频会卡顿
        video.setFrameRate(15);
        //编码属性
        EncodingAttributes attrs = new EncodingAttributes();
        attrs.setFormat("mp4");
        attrs.setAudioAttributes(audio);
        attrs.setVideoAttributes(video);
        //开始转格式
        Encoder encoder = new Encoder();
        MultimediaObject multimediaObject = new MultimediaObject(new File(oldPath));
        try {
            encoder.encode(multimediaObject, new File(newPath), attrs);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return newPath;
    }
}